﻿using ProtoBuf;
using SyncCore.Sync.Models;
using SyncDemo.Sync.Models;
using System.Collections.Specialized;

namespace SyncCore.Sync
{
    ///<summary>端口地址信息列表。</summary>
    [ProtoContract]
    public class AddressPortStateList : INotifyCollectionChanged
    {
        #region defines

        [ProtoContract]
        public class AddressPortTimestumbInfo
        {
            #region props

            [ProtoMember(1)]
            public AddressPortInfo BoardcastInfo { get; set; }

            [ProtoMember(2)]
            public DateTime Time { get; set; }

            [ProtoMember(3)]
            public bool IsHostServer { get; set; } // 是否创建了自己的房间作为房主。

            [ProtoMember(4)]
            public AddressPortInfo HostServer { get; set; } // 作为房主的监听地址。

            [ProtoMember(5)]
            public bool IsGameExecuteing { get; set; }

            [ProtoMember(6)]
            public bool IsJoinedRoom { get; set; } // 是否加入到了一个房间。

            [ProtoMember(7)]
            public AddressPortInfo RoomServer { get; set; }  // 加入到的房间的地址。

            #endregion

            #region ctors

            public AddressPortTimestumbInfo()
            {

            }

            public AddressPortTimestumbInfo(AddressPortInfo info, DateTime time)
            {
                BoardcastInfo = info;
                Time = time;
            }

            #endregion

            #region methods

            public bool IsIdle()
            {
                return IsHostServer == false && IsJoinedRoom == false;
            }

            #endregion


        }
        #endregion

        #region events

        public event NotifyCollectionChangedEventHandler? CollectionChanged;

        #endregion

        #region props

        [ProtoMember(1)]
        public List<AddressPortTimestumbInfo> Items { get; set; }

        #endregion

        #region ctors

        public AddressPortStateList()
        {
            Items = new List<AddressPortTimestumbInfo>();
        }

        #endregion

        #region methods

        public AddressPortTimestumbInfo AddNow(AddressPortInfo info)
        {
            return Add(info, DateTime.Now);
        }

        public AddressPortTimestumbInfo Add(AddressPortInfo info, DateTime time)
        {
            var timestumbInfo = Items.FirstOrDefault(i => i.BoardcastInfo == info);

            if (timestumbInfo != null)
            {
                timestumbInfo.Time = time;
            }
            else
            {
                var newTimestumbInfo = new AddressPortTimestumbInfo(info, time);
                Items.Add(newTimestumbInfo);
            }

            return timestumbInfo;
        }

        ///<summary>获得可用的广播地址。</summary>
        public IEnumerable<AddressPortInfo> GetIdleAddressPortBoardcastInfos()
        {
            var now = DateTime.Now;
            foreach (var addressPortTimestumbInfo in Items)
            {
                var delta = now - addressPortTimestumbInfo.Time;
                var isIdle = addressPortTimestumbInfo.IsIdle();
                if (delta.TotalMinutes < 1 && isIdle) // 将两分钟以内的发送，并且返回的是闲置的服务器。
                {
                    yield return addressPortTimestumbInfo.BoardcastInfo;
                }
            }
        }

        ///<summary>获得在线的服务器端。</summary>
        public IEnumerable<AddressPortInfo> GetIdleServerAddressPortInfos()
        {
            var now = DateTime.Now;
            foreach (var addressPortTimestumbInfo in Items)
            {
                var delta = now - addressPortTimestumbInfo.Time;
                var isServer = addressPortTimestumbInfo.IsHostServer;
                var isGameExecuting = addressPortTimestumbInfo.IsGameExecuteing;
                if (delta.TotalMinutes < 1 && isServer && isGameExecuting) // 将两分钟以内的发送，并且返回的是闲置的服务器。
                {
                    yield return addressPortTimestumbInfo.HostServer;
                }
            }
        }

        ///<summary>获得在线客户端的整体数据状态。</summary>
        public ClientHallSummaryInfo GetClientHallSummaryInfo()
        {
            var idleBoardcasts = GetIdleAddressPortBoardcastInfos().ToArray();

            var servers = GetIdleServerAddressPortInfos().ToArray();

            return new ClientHallSummaryInfo() { IdleBoardcasts = idleBoardcasts, Servers = servers };
        }

        #endregion

    }
}
